<?php
// +----------------------------------------------------------------------+
// |       	     Copyright (c) 2013 Carlos Mora Molina    			      |
// +----------------------------------------------------------------------+
// | Este programa es software libre. Puede distribuirlo  y/o modificarlo |
// | bajo los términos de la  licencia GNU General Public License  tal  y |
// | como la publica la Fundación de Software Libre, bajo la denominación |
// | GPL, en su versión 2 o posterior (versión inglesa).                  |
// |                                                                      |
// | This program is free software. You can redistribute it and/or modify |
// | it under the terms of the GNU General Public License as published by |
// | the Free Software Foundation; either version 2 or later of the GPL.  |
// +----------------------------------------------------------------------+
// | Autores/Authors:                                                     |
// |          Carlos Mora <ozonosp@gmail.com>                             |
// +----------------------------------------------------------------------+
//
// $Id: Exp $

 /**
  * Manejador de objetos de tipo __U_TABLE_NAME__
  * __DATE_VERSION__
  * NO MODIFIQUE ESTA CLASE, si desea modificar algo agregelo al archivo __U_TABLE_NAME__.tpl dentro
  * del directorio auto_include y se incluirá automáticamente.
  * Si desea incluir contenido en el contructor no lo haga en este archivo, declare la funcion
  * constructor($param1 = NULL, $param2 = NULL, $param3 = NULL, $param4 = NULL) en auto_include
  * y será llamada cada vez que se contruya la clase.
  */
class __U_TABLE_NAME__Dao {

	private $columns;
	private $index;
	private $orden;
	private $limit;
	private $searchLike;
	
		/**
	 * Contructor de la clase
	 * Si desea añadir algo en el contructor no lo haga modificando la plantilla sino declarando
	 * constructor($param1 = NULL, $param2 = NULL, $param3 = NULL, $param4 = NULL) en el archivo de include, 
	 * constructor recibirá los parametros en el mismo orden y se llamará cada vez que se construya la clase
	 * @param string $param1
	 * @param string $param2
	 * @param string $param3
	 * @param string $param4
	 */
    function __U_TABLE_NAME__Dao($param1 = NULL, $param2 = NULL, $param3 = NULL, $param4 = NULL) {
    	
    	//Asignamos el array de tipos
__FIELDS_DATA_TYPES__
    	
    	/**
    	 * Si en el fichero de includes se añade constructor($param1 = NULL, $param2 = NULL, $param3 = NULL, $param4 = NULL)
    	 * se llamará cada vez que se construya la clase
    	 */
		if(method_exists($this,'constructor')) $this->constructor($param1, $param2, $param3, $param4);
    }
	
	/**
	 * Establece la ordenación que se utilizará en las consultas
	 * Para random setOrder('','RAND ()');
	 * Para borrar la ordenación llamar a la función en vacio setOrder();
	 * @param string $fild Nombre del campo/s sobre el que ordenar
	 * @param ASC|DESC|RAND() Tipo de ordenación
	 */
	function setOrder($field = '',$orden = ''){
		if($field == '' && $orden == ''){
			$this->orden = '';
			return false;
		}
		$this->orden = "ORDER BY $field $orden";
	}
	
	/**
	 * Establece si se buscará con like o con =
	 * @param bool $bool
	 */
	function setLike($bool){
		$this->searchLike = $bool;
	}

	/**
	 * Establece el límite de filas a devolver
	 * setLimit(); elimina la limitación
	 * @param integer $from
	 * @param integer $to;
	 */
	function setLimit($from = 0,$to = 0){
		if($to === 0){
			$this->limit = NULL;
			return false;
		}else if($from > $to || $to < 1){
			error_log("La limitación introducida no es válida en __U_TABLE_NAME__Dao");
			return false;
		}
		$this->limit = "LIMIT $from,$to";
		return true;
	}
		
	/**
	 * Devuelve un objeto __U_TABLE_NAME__
	 * @return __U_TABLE_NAME__
	 */
	function createValueObject() {
		return new __U_TABLE_NAME__();
	}
	
	
	/**
	 * Recibe una consulta y devuelve un array de objetos __U_TABLE_NAME__ rellenos
	 * @param Database $conn
	 * @param sql $sql
	 * @return multitype:
	 */
	function listQuery($conn, $sql) {
		$searchResults = array();
		$result = $conn->execute($sql);
		while ($row = $conn->nextRow($result)) { //Para cada fila
			$__U_TABLE_NAME__ = $this->createValueObject();	//Creamos un objeto vacio
			foreach($row as $index => $value){	//Para cada columna
				$__U_TABLE_NAME__->$index = $value;	//Ajustamos el valor
			}
			$searchResults[] = $__U_TABLE_NAME__;
		}	
		return $searchResults;
	}
	
	/**
	 * Rellena un objeto dado con los datos generados por la consulta
	 * @param unknown $conn
	 * @param unknown $sql
	 * @param unknown $valueObject
	 */
	function singleQuery($conn, $sql, $valueObject) {
		$result = $conn->execute($sql);
		if ($row = $conn->nextRow($result)) { //Para la primera fila
			foreach($row as $index => $value){	//Para cada columna
				$valueObject->$index = $value;	//Ajustamos el valor
			}
		}	
		return $valueObject;
	}

	/**
	 * Obtiene un objeto a partir de su id
	 * @param Datasource $conn
	 * @param __U_TABLE_NAME__ $valueObject
	 * @return __U_TABLE_NAME__
	 */
    function load($conn, $valueObject) {
          $sql = "SELECT * FROM __TABLE_NAME__ __WHERE_CLAUSULE__";
          return $this->singleQuery($conn, $sql, $valueObject);
    }
    
    /**
     * Devuelve un array de objetos __U_TABLE_NAME__ con todos los registros de la BBDD
     * Se le puede establecer un limit mediante setLimit(FROM,TO);
     * @param Datasource $conn
     * @return Array __U_TABLE_NAME__
     */
    function loadAll($conn) {
          $sql = "SELECT * FROM __TABLE_NAME__ $this->orden $this->limit";
          $searchResults = $this->listQuery($conn, $sql);
          return $searchResults;
    }

    /**
     * Recibe un objeto __U_TABLE_NAME__ con algunos datos rellenos
     * y busca todas las coincidencias en la BBDD, según hayamos establecido setOrdenacion y
     * setLike devolverá el resultado ordenado de una forma u otra.
     * DEVUELVE UN ÚNICO RESULTADO
     * @param DataSource $conn
     * @param Articulos_compra $valueObject
     * @return array Articulos_compra
     */
    function searchMatchingSingle($conn, $valueObject) {
    	$actual_limit = $this->limit; //Guardamos el límite actual
    	$this->setLimit(0,1); //Establecemos un limite de 1
    	$result = $this->searchMatching($conn, $valueObject);
    	$this->limit = $actual_limit; //Reestablecemos el límite como estuviese antes de la consulta
    	return array_pop($result);
    }
    
    /**
     * Recibe un objeto __U_TABLE_NAME__ con algunos datos rellenos
	 * y busca todas las coincidencias en la BBDD, según hayamos establecido setOrdenacion,
	 * setLike y setLimit devolverá el resultado ordenado de una forma u otra y con el límite dado
     * @param DataSource $conn
     * @param __U_TABLE_NAME__ $valueObject
     * @return array __U_TABLE_NAME__
     */
	function searchMatching($conn, $valueObject) {
		$sql = "SELECT * FROM __TABLE_NAME__ WHERE 1 ";
    	
		foreach($this->columns as $index => $dataType){ //Para cada una de las columnas comprobamos si hay un valor
			if (gettype($valueObject->$index) != 'NULL') { //Si tiene un valor asignado generamos el sql
				if($this->searchLike && gettype($valueObject->$index)=='string'){
					$sql .= "AND $index LIKE '".$conn->escapeString($valueObject->$index)."%' "; //Es un string
				}else if(strpos($dataType['Type'],'blob') !== false){ 
					$sql .= "AND $index = ".$conn->escapeString($valueObject->$index)." "; //Es un dato binario, debe ir sin comillas
				}else{
					$sql .= "AND $index = '".$conn->escapeString($valueObject->$index)."' "; //Buscamos con comillas
				}
			}
		}  
    
		$sql = $sql." $this->orden $this->limit"; //Establecemos la ordenación y el límite
		$searchResults = $this->listQuery($conn, $sql);
		
		return $searchResults;
	}

	
	/**
	 * Crea una nueva linea en la BBDD con los datos del objeto __U_TABLE_NAME__ recibido
	 * @param Datasource $conn
	 * @param __U_TABLE_NAME__ $valueObject
	 * @return mysql result
	 */
	function create($conn, $valueObject) {
		foreach($this->columns as $index => $dataType){ //Para cada una de las columnas comprobamos si hay un valor
			if (gettype($valueObject->$index) != 'NULL') { //Si tiene un valor asignado generamos el sql
				if(!isset($fields)) $fields = $index; //En la primera vuelta insertamos el valor
					else $fields .= ", $index"; //EL resto añadimos el valor
				
				if(!isset($values)) $values = ''; //En la primera vuelta insertamos el valor
					else $values .= ", "; //EL resto añadimos el valor
					
				if(strpos($dataType['Type'],'blob') !== false){ //lo añadimos a la lista de valores
					$values .= $conn->escapeString($valueObject->$index);
				}else{
					$values .= "'".$conn->escapeString($valueObject->$index)."'"; //Para todos los demas campos
				}
				
			}
		}
		$sql = "INSERT INTO __TABLE_NAME__ ($fields) VALUES ($values)";
		
		$result = $conn->execute($sql);
		return $result;
	}
	
		
	/**
	 * Actualiza los datos del objeto dado en la BBDD
	 * @param Datasource $conn
	 * @param __U_TABLE_NAME__ $valueObject
	 * @return mysql result
	 */
	function save($conn, $valueObject) {

		foreach($this->columns as $index => $dataType){ //Para cada una de las columnas comprobamos si hay un valor
			if (gettype($valueObject->$index) != 'NULL') { //Si tiene un valor asignado generamos el sql						
				if(strpos($dataType['Type'],'blob') !== false){ //Si no es binario
					if(!isset($sql)) $sql = "$index = ".$conn->escapeString($valueObject->$index); //En la primera vuelta insertamos el valor
						else $sql .= ", $index = ".$conn->escapeString($valueObject->$index); //EL resto añadimos el valor
				}else{
					if(!isset($sql)) $sql = "$index = '".$conn->escapeString($valueObject->$index)."'"; //En la primera vuelta insertamos el valor
						else $sql .= ", $index = '".$conn->escapeString($valueObject->$index)."'"; //EL resto añadimos el valor
				}
			}
		}
		$sql = "UPDATE __TABLE_NAME__ SET $sql __WHERE_CLAUSULE__";
		$result = $conn->execute($sql);
		return $result;
	}
	

	/**
	 * Elimina el Objeto dado de la BBDD
	 * @param Datasource $conn
	 * @param __U_TABLE_NAME__ $valueObject
	 * @return boolean
	 */
    function delete($conn, $valueObject) {

		$sql = "DELETE FROM __TABLE_NAME__ __WHERE_CLAUSULE__";
		$result = $conn->execute($sql);

		if ($result != 1) {
              error_log("Ocurrió un problema borrando datos en __U_TABLE_NAME__");
			return false;
		}
		return true;
	}
	
	/**
	 * ¡¡UTILIZAR CON MUCHO CUIDADO!!
	 * Recibe un objeto __U_TABLE_NAME__ con algunos datos rellenos
	 * y BORRA TODAS las coincidencias de la base de datos
	 * @param DataSource $conn
	 * @param __U_TABLE_NAME__ $valueObject
	 * @return true|false
	 */
	function deleteMatching($conn, $valueObject) {

		foreach($this->columns as $index => $dataType){ //Para cada una de las columnas comprobamos si hay un valor
			if (gettype($valueObject->$index) != 'NULL') { //Si tiene un valor asignado generamos el sql
				if(!isset($sql)) $sql = "$index = '".$conn->escapeString($valueObject->$index)."' "; //La primera vez sin AND
					else $sql .= "AND $index = ".$conn->escapeString($valueObject->$index); //El resto con
			}
		}
		
		$sql = "DELETE FROM __TABLE_NAME__ WHERE $sql";
		return $conn->execute($sql);
	
	}

	/**
	 * Devuelve el número de filas para la consulta
	 * @param Datasource
	 * @return Array
	 */
    function countAll($conn) {
    	
          $sql = "SELECT count(*) FROM __TABLE_NAME__";
          $allRows = 0;
          $result = $conn->execute($sql);
          
          if ($row = $conn->nextRow($result))
                $allRows = $row[0];

          return $allRows;
    }
  
    /**
	 * Devuelve el último id insertado para la conexión actual
	 * @param Datasource
	 * @return id|false
	 */
    function lastId($conn){
    	$result = $conn->execute('SELECT LAST_INSERT_ID()');
		if($row = $conn->nextRow($result))	return array_pop($row); //Devolvemos el id
		return false;
    }
    
    
    // ###############################################	CODIGO AUTO INCLUIDO POR EL USUARIO ####################################
    

    __AUTO_INCLUDE__

}

?>